package com.minisoft.jd.seckill;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
public class Login {

    final static String headerAgent = "User-Agent";
    // Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36
    // Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1
    final static String headerAgentArg = "JD4iPhone/10.1.6 CFNetwork/1312 Darwin/21.0.0";
    final static String Referer = "Referer";
    final static String RefererArg = "https://passport.jd.com/new/login.aspx";
    final static int scanTotal = 60;//超过这个次数没有扫码成功，就是过期了

    public static void main(String[] args) throws Exception {
        login("jue.png","", false);
    }


    private static boolean isWindows() {
        String os = System.getProperty("os.name");
        return os.toLowerCase().startsWith("win");
    }

    public static String login(String imageName, String oldCookie, boolean loginWithEmail) throws Exception {
        Map<String,String> headers = new HashMap<>();
        headers.put(headerAgent, headerAgentArg);
        headers.put(Referer, RefererArg);
        Long now = System.currentTimeMillis();
        String url = "https://qr.m.jd.com/show?appid=133&size=147&t=" + now;
        HttpResponse response = HttpUtil.createGet(url).headerMap(headers, true).execute();
        String token = response.getCookie("wlfstk_smdl").getValue();

        if (!loginWithEmail && isWindows()) {
            close(imageName);
            IoUtil.write(new FileOutputStream(imageName),true,response.bodyBytes());
            Runtime.getRuntime().exec("cmd /c "+ imageName);
        } else {
            try {
                MailSender.sendLogin(imageName, response.bodyStream());
            } catch (Exception e) {
                //如果发送失败，暂停10秒，返回，重新发起
                log.error("发送登录邮件异常，30秒后再重试",e);
                ThreadUtil.sleep(30, TimeUnit.SECONDS);
                return null;
            }
        }
        List<HttpCookie> cookies = response.getCookies();
        StringBuilder sb = new StringBuilder();
        for (HttpCookie cookie : cookies) {
            if (sb.length() > 0) {
                sb.append("; ");
            }
            sb.append(cookie.getName());
            sb.append('=');
            sb.append(cookie.getValue());
        }
        headers.put("Cookie", sb.toString());
        int index = 1;
        while (index++  < scanTotal) {
            String checkUrl = "https://qr.m.jd.com/check?appid=133&callback=jQuery" + (int) ((Math.random() * (9999999 - 1000000 + 1)) + 1000000) + "&token=" + token + "&_=" + System.currentTimeMillis();
            HttpResponse httpResponse = HttpUtil.createGet(checkUrl).headerMap(headers, true).execute();
            String qrCode = httpResponse.body();
            log.debug("【{}】{}",imageName,qrCode);
            if (qrCode.contains(": 200")){
                if (isWindows()) {
                    close(imageName);
                    FileUtil.del(new File(imageName));//删除二维码
                }
                log.info("【{}】已完成二维码扫描登录",imageName);
                String ticket = qrCode.split("\"ticket\" : \"")[1].split("\"\n}\\)")[0];
                checkUrl = "https://passport.jd.com/uc/qrCodeTicketValidation?t=" + ticket;
                httpResponse = HttpUtil.createGet(checkUrl).headerMap(headers, true).execute();
                return getNewCookie(httpResponse,oldCookie);
            }
            Thread.sleep(3000);
        }
        return null;
    }

    public static String getNewCookie(HttpResponse httpResponse, String oldCookie) {
        Map<String,String> cookieMap = new HashMap<>();
        List<HttpCookie> cookies = httpResponse.getCookies();
        cookies.forEach(cookie -> cookieMap.put(cookie.getName(),cookie.getValue()));
        String[] cookieStrs = oldCookie.split("; ");
        StringBuilder sb = new StringBuilder();
        for (String cookieStr : cookieStrs) {
            if (sb.length() > 0) {
                sb.append("; ");
            }
            String[] cookieArray = cookieStr.split("=");
            sb.append(cookieArray[0]).append('=');
            String value = StrUtil.nullToDefault(cookieMap.get(cookieArray[0]), cookieArray[1]);
            sb.append(value);
        }
        return sb.toString();
    }

    public static void close(String imageName) {
        WinDef.HWND hWnd;
        final User32 user32 = User32.INSTANCE;
        user32.EnumWindows((hWnd1, arg1) -> {
            char[] windowText = new char[512];
            user32.GetWindowText(hWnd1, windowText, 512);
            String wText = Native.toString(windowText);
            if (wText.isEmpty()) {
                return true;
            }
            if (wText.contains(imageName)) {
                hWnd1 = User32.INSTANCE.FindWindow(null, wText);
                WinDef.LRESULT lresult = User32.INSTANCE.SendMessage(hWnd1, 0X10, null, null);
            }
            return true;
        }, null);
    }

}
